package org.example;


import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;

//TODO  多线程操作线程池暂不考虑
//小试牛刀之后的线程池
public class MyThreadPool {

    //拒绝策略
    private RejectPolicy rejectPolicy = new RejectPolicy() {
        @Override
        public void reject(Runnable task, MyThreadPool threadPool) {
            //默认策略 啥也不管 直接打印即可
            System.out.println("任务队列已满 禁止加入任务");
        }
    };

    //标志位用于优雅的关闭线程池 即执行完当前所有任务后关闭线程池
    private boolean isRunning = true;

    //记录线程数量
    public int threadCount = 0;

    //核心线程数量 默认为10
    private int corePoolSize = 10;

    //最大线程数量 默认和核心线程数量一致
    private int maxPoolSize = 10;



    //核心线程容器
    List<Worker> threadList = new LinkedList<>();

    //额外线程容器
    List<Worker> extraThreadList = new LinkedList<>();

    //任务队列 用阻塞队列  相应的 防止他爆 要拒绝策略
    private final BlockingQueue<Runnable> taskQueue = new LinkedBlockingQueue<>(10);

    //构造方法 线程进容器 然后启动
    public MyThreadPool() {

    }

    //构造方法 线程进容器 然后启动  可以传 核心线程数量
    public MyThreadPool(int corePoolSize) {
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = corePoolSize;
    }

    //构造方法 线程进容器 然后启动  可以传 核心线程数量 和 最大线程数量
    public MyThreadPool(int corePoolSize, int maxPoolSize) {
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;

    }

    //构造方法 线程进容器 然后启动  可以传 核心线程数量
    public MyThreadPool(int corePoolSize, RejectPolicy rejectPolicy) {
        this.rejectPolicy = rejectPolicy;
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = corePoolSize;
    }

    //构造方法 线程进容器 然后启动  可以传 核心线程数量 和 最大线程数量
    public MyThreadPool(int corePoolSize, int maxPoolSize, RejectPolicy rejectPolicy) {
        this.rejectPolicy = rejectPolicy;
        this.corePoolSize = corePoolSize;
        this.maxPoolSize = maxPoolSize;

    }


    //统一放入任务队列 队满可考虑创建额外线程   满了采取拒接策略
    public void execute(Runnable task) {
        if (isRunning) {
            //核心线程 可以直接创建
            if (corePoolSize > threadCount) {
                Worker worker = new Worker(task);
                threadList.add(worker);
                worker.start();
                threadCount++;
                System.out.println("创建线程成功 目前线程数量为：" + threadCount);
            } else {
                //将任务添加到任务队列中
                boolean success = taskQueue.offer(task);
                if (!success) {
                    //判断是否可以找额外线程 不行则要决绝策略
                    if (threadCount < maxPoolSize) {
                        Worker worker = new Worker(task,false);
                        extraThreadList.add(worker);
                        worker.start();
                        threadCount++;
                        System.out.println("额外创建线程成功 目前线程数量为：" + threadCount);
                    } else {
                        rejectPolicy.reject(task, this);
                    }
                } else {
                    System.out.println("任务提交成功");
                }
            }

        }

    }

    //优雅的关闭 只需要设置标志位
    public void shutdown() {
        isRunning = false;
    }



    //内部类 包装一个线程  他有任务属性
    class Worker extends Thread {
        private Runnable task;


        //标志位  是否是核心线程  额外线程 则许久没拿到任务 就被销毁 他有api
        private boolean isCore = true;


        public Worker(Runnable task) {
            this.task = task;
        }
        public Worker(Runnable task, boolean isCore) {
            this.task = task;
            this.isCore = isCore;
        }

        //当前任务执行完就去读队列里面的任务
        @Override
        public void run() {
            if (task != null) {
                task.run();
            }
            while (isRunning || !taskQueue.isEmpty()) {
                try {
                    //TODO  可以提出成构造函数 最后一步了 暂不考虑了
                    //从任务队列中取出一个任务
                    task = taskQueue.poll(1, java.util.concurrent.TimeUnit.SECONDS);

                    //没拿到 则销毁额外线程

                    if(task == null){
                        if(!isCore){
                            break;
                        }
                    }
                    else{
                        task.run();

                    }
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

            }
            extraThreadList.remove(this);
            threadCount--;

        }

    }


}
